const { v4: uuidv4 } = require('uuid')
const cloneDeep = require('lodash/cloneDeep')
const rxdb = require('./rxdb')
const { addTitle, getUGM, translate } = require('./handleData')

class Autoplan {
  constructor({ data, bim, elements, names }) {
    this.data = addTitle('data', { data, bim })
    this.bim = addTitle('bim', { data, bim })
    this.elements = addTitle('elements', { data, bim, elements })
    this.roomNames = names
  }

  manualplan = ({ stage, point, uuidList, selectedIds, type }) => {
    if (!uuidList || !uuidList.length) {
      return
    }
    if (!stage.includes('concrete')) {
      let room = this.bim.docs[selectedIds.find(i => this.bim.docs[i].definition === 'room')]
      if (!room) {
        const roomPolygonPoints = this.bim.cols.room.map(i => i.points)
        const roomIndex = roomPolygonPoints.findIndex(polygonPoints => this.isInPolygon(point, polygonPoints))
        if (roomIndex === -1) {
          console.log('没有此站点能归属的房间')
          return
        }
        room = this.bim.cols.room[roomIndex]
      }
      if (!room) {
        return
      }
      const mainwalls = this.bim.cols.mainwall
        .filter(i => i.room === room.id)
        .filter(i => uuidList.includes(i.original) || uuidList.includes(i.data[0]))
        .map(i => i.data[0])
      const drywalls = this.bim.cols.drywall
        .filter(i => i.room === room.id)
        .filter(i => uuidList.includes(i.original) || uuidList.includes(i.data[0]))
        .map(i => i.data[0])
      const doors = this.bim.cols.door
        .filter(o => o.room === room.id)
        // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
        .map(i => i.id)
      const windows = this.bim.cols.window
        .filter(o => o.room === room.id)
        // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
        .map(i => i.id)
      if (mainwalls.length === 0 && drywalls.length === 0) {
        console.log('没有此站点能扫到的墙')
        return
      }
      const allWallsLength = mainwalls.length + drywalls.length
      if (allWallsLength < 3) {
        console.log('此站点能扫到的墙少于3条')
        return
      }
      const oldScanstations = this.bim.cols.scanstation.filter(i => i.room === room.id)
      const newScanstations = []
      oldScanstations.forEach((o, index) => newScanstations.push({ ...o, id: room.id + `0${index + 1}` }))
      const scanstation = {
        point,
        id: room.id + `0${newScanstations.length + 1}`,
        mainwalls,
        drywalls,
        doors,
        windows,
        name: `${room.name}${translate('scanstation')}0${newScanstations.length + 1}`,
        room: room.id,
        definition: 'scanstation',
        isNewScan: type,
        stage: ['masonry', 'plaster']
      }
      newScanstations.push(scanstation)
      rxdb.deleteDocs(
        oldScanstations.map(i => i.id),
        'scanstation',
        this.data,
        this.bim,
        this.setData,
        this.setBIM
      )
      rxdb.addDocs(newScanstations, 'scanstation', this.data, this.bim, this.setData, this.setBIM)
    } else {
      const mainwalls = this.data.cols.line
        .filter(i => i.layer === this.data.cols.layer.find(o => o.type === 'MainWall').id)
        .filter(i => uuidList.includes(i.id))
        .map(i => i.id)
      if (mainwalls.length < 3) {
        console.log('此站点能扫到的墙少于3条')
        return
      }
      const bimId = this.bim.cols.bim[0].id
      const scanstationsNumber = this.bim.cols.scanstation.length
      const scanstation = {
        point,
        id: uuidv4(),
        mainwalls,
        name: `${translate('scanstation')}0${scanstationsNumber + 1}`,
        definition: 'scanstation',
        bim: bimId,
        isNewScan: type,
        stage: ['concrete']
      }
      rxdb.addDocs([scanstation], 'scanstation', this.data, this.bim, this.setData, this.setBIM)
    }
    return true
  }

  addApartment = ({ result }) => {
    if (!result.length) return
    const bim = cloneDeep(this.bim)
    const bimId = bim.cols.bim[0].id
    const apartmentsNumber = bim.cols.apartment.length
    const newApartments = []
    const roomsToUpdate = []
    result.forEach((regionIds, index) => {
      const apartmentId = uuidv4()
      const newApartment = {
        name: `${translate('apartment')}0${apartmentsNumber + index + 1}`,
        id: apartmentId,
        bim: bimId,
        definition: 'apartment'
      }
      newApartments.push(newApartment)
      const roomIds = bim.cols.room.filter(o => regionIds.includes(o.mergeNum.toString())).map(p => p.id)
      roomIds.forEach(roomId => roomsToUpdate.push({ ...bim.docs[roomId], apartment: apartmentId }))
    })
    rxdb.addDocs(newApartments, 'apartment', this.data, this.bim, this.setData, this.setBIM)
    rxdb.updateDocs(roomsToUpdate, null, this.data, this.bim, this.setData, this.setBIM)
    return getUGM({ data: this.data, bim: this.bim })
  }

  new_autoplan = ({ result, stage }) => {
    console.log('new_autoplan')
    const { concrete, masonry } = result
    const data = cloneDeep(this.data)
    const bim = cloneDeep(this.bim)
    if (!stage.includes('concrete')) {
      const roomIds = bim.cols.room.map(i => i.id)
      const drywallIds = bim.cols.drywall.map(i => i.id)
      const mainwallIds = bim.cols.mainwall.map(i => i.id)
      const doorIds = bim.cols.door.map(i => i.id)
      const windowIds = bim.cols.window.map(i => i.id)
      const apartmentIds = bim.cols.apartment.map(i => i.id)
      const scanstationIds = bim.cols.scanstation.filter(i => i.room).map(i => i.id)
      rxdb.deleteDocs(
        [...roomIds, ...drywallIds, ...mainwallIds, ...doorIds, ...windowIds, ...apartmentIds, ...scanstationIds],
        null,
        this.data,
        this.bim,
        this.setData,
        this.setBIM
      )

      const newRooms = []
      const newMainWalls = []
      const newDryWalls = []
      const newDoors = []
      const newWindows = []
      const newScanstations = []

      const roomsNumber = bim.cols.room.length
      const MainWallsNumber = bim.cols.mainwall.length
      const DryWallsNumber = bim.cols.drywall.length
      const doorsNumber = bim.cols.door.filter(i => i.room).length
      const windowsNumber = bim.cols.window.filter(i => i.window).length

      const bimId = bim.cols.bim[0].id

      for (let i = 0; i < masonry.length; i++) {
        const item = masonry[i]
        const { profile_points: points, region_id, components, stations, tags } = item

        const roomName = tags[0]
        const roomId = uuidv4()
        const room = {
          points: points.map(id => [data.docs[id].location[0], data.docs[id].location[1]]),
          name: roomName || `${translate('room')}0${roomsNumber + newRooms.length + 1}`,
          apartment: undefined,
          bim: bimId,
          id: roomId,
          mergeNum: region_id,
          definition: 'room',
          isNewScan: true
        }
        newRooms.push(room)

        for (let o = 0; o < components.length; o++) {
          const id = components[o]
          const doc = data.docs[id]
          if (!doc || !doc.layer) continue
          const type = data.docs[doc.layer].type.toLowerCase()
          switch (type) {
            case 'mainwall':
              const newMainWall = {
                data: [doc.id],
                lines: [[doc.start, doc.end]],
                name: `${translate('MainWall')}0${MainWallsNumber + newMainWalls.length + 1}`,
                room: roomId,
                original: doc.original,
                id: uuidv4(),
                definition: 'mainwall',
                isNewScan: true
              }
              newMainWalls.push(newMainWall)
              break
            case 'drywall':
              const newDrywall = {
                data: [doc.id],
                lines: [[doc.start, doc.end]],
                name: `${translate('DryWall')}0${DryWallsNumber + newDryWalls.length + 1}`,
                room: roomId,
                original: doc.original,
                id: uuidv4(),
                definition: 'drywall',
                isNewScan: true
              }
              newDryWalls.push(newDrywall)
              break
            case 'door':
              const newDoor = {
                data: [],
                lines: [[doc.start, doc.end]],
                name: `${translate('door')}0${doorsNumber + newDoors.length + 1}`,
                room: roomId,
                material: doc.material,
                id: uuidv4(),
                definition: 'door',
                isNewScan: true
              }
              newDoors.push(newDoor)
              break
            case 'window':
              const newWindow = {
                data: [],
                lines: [[doc.start, doc.end]],
                name: `${translate('window')}0${windowsNumber + newWindows.length + 1}`,
                room: roomId,
                material: doc.material,
                id: uuidv4(),
                definition: 'window',
                isNewScan: true
              }
              newWindows.push(newWindow)
              break
            default:
          }
        }

        if (
          tags.includes('厨房') ||
          tags.includes('卫生间') ||
          tags.includes('阳台') ||
          tags.includes('楼梯') ||
          tags.includes('电梯')
        ) {
          continue
        }

        for (let o = 0; o < stations.length; o++) {
          const { coordinate, scan_walls: lines } = stations[o]
          const drywalls = [...newDryWalls]
            .filter(o => o.room === roomId)
            .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
            .map(i => i.data[0])
          const mainwalls = [...newMainWalls]
            .filter(o => o.room === roomId)
            .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
            .map(i => i.data[0])
          const doors = [...newDoors]
            .filter(o => o.room === roomId)
            // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
            // .map(i => i.data[0])
            .map(i => i.id)
          const windows = [...newWindows]
            .filter(o => o.room === roomId)
            // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
            // .map(i => i.data[0])
            .map(i => i.id)
          const scanstation = {
            point: coordinate,
            id: roomId + `0${o + 1}`,
            drywalls,
            mainwalls,
            doors,
            windows,
            name: `${room.name}${translate('scanstation')}0${o + 1}`,
            room: roomId,
            definition: 'scanstation',
            stage: ['masonry', 'plaster'],
            isNewScan: true
          }
          newScanstations.push(scanstation)
        }
      }
      rxdb.addDocs([...newRooms, ...newScanstations], null, this.data, this.bim, this.setData, this.setBIM)
      rxdb.updateDocs(
        [...newMainWalls, ...newDryWalls, ...newDoors, ...newWindows],
        null,
        this.data,
        this.bim,
        this.setData,
        this.setBIM
      )
    } else {
      const newScanstations = []
      const scanstationIds = bim.cols.scanstation.filter(i => !i.room).map(i => i.id)
      rxdb.deleteDocs(scanstationIds, null, this.data, this.bim, this.setData, this.setBIM)
      concrete[0].stations.forEach(i => {
        const { coordinate, scan_walls } = i
        const bimId = bim.cols.bim[0].id
        const scanstationsNumber = bim.cols.scanstation.length
        const scanstation = {
          point: coordinate,
          id: uuidv4(),
          mainwalls: scan_walls.filter(p => concrete[0].components.includes(p)),
          name: `测量站点${translate('scanstation')}0${scanstationsNumber + newScanstations.length + 1}`,
          definition: 'scanstation',
          bim: bimId,
          stage: ['concrete'],
          isNewScan: true
        }
        newScanstations.push(scanstation)
      })
      rxdb.addDocs(newScanstations, null, this.data, this.bim, this.setData, this.setBIM)
    }

    return getUGM({ data: this.data, bim: this.bim })
  }

  create_point(x, y) {
    const newPId = uuidv4()
    const newPoint = {
      ...data.cols.point[0],
      id: newPId,
      location: [x, y, 0],
      name: newPId,
      value: newPId,
      _id: null,
      isNew: true,
      updatedAt: null
    }
    return newPoint
  }

  autoplan = ({ cb, stage, roomData, scanstation, separators, deleteSeparator, orientationAndDimension }) => {
    const data = cloneDeep(this.data)
    const bim = cloneDeep(this.bim)
    const newDataDocs = cloneDeep(this.data.docs)
    // const clonedTexts = cloneDeep(this.data.cols.text)
    // const newTexts = clonedTexts.map(data => {
    //   const newId = uuidv4()
    //   return {
    //     ...data,
    //     id: newId,
    //     name: newId,
    //     value: newId,
    //     definition: 'displayText'
    //   }
    // })
    // this.data.cols.newText = newTexts
    if (!scanstation) {
      cb(false)
      return
    }
    if (stage.includes('concrete')) {
      const scanstationIds = bim.cols.scanstation.filter(o => !o.room).map(i => i.id)
      rxdb.deleteDocs(scanstationIds, 'scanstation', this.data, this.bim, this.setData, this.setBIM)

      const newScanstations = []
      if (scanstation.length === 1 && scanstation[0].length > 2) {
        scanstation = scanstation[0]
      }
      scanstation.forEach(i => {
        const [point, uuidList] = i
        if (uuidList && uuidList.includes) {
          const mainwalls = data.cols.line
            .filter(i => i.layer === data.cols.layer.find(o => o.type === 'MainWall').id)
            .filter(i => uuidList.includes(i.id))
            .map(i => i.id)
          if (mainwalls.length === 0) {
            console.log('没有此站点能扫到的墙')
            cb({ 手动规划: false })
            return
          }
          const bimId = bim.cols.bim[0].id
          const scanstationsNumber = bim.cols.scanstation.length
          const scanstation = {
            point,
            id: uuidv4(),
            mainwalls,
            name: `测量站点${translate('scanstation')}0${scanstationsNumber + newScanstations.length + 1}`,
            definition: 'scanstation',
            bim: bimId,
            stage: ['concrete']
          }
          newScanstations.push(scanstation)
        }
      })
      rxdb.addDocs(newScanstations, 'scanstation', this.data, this.bim, this.setData, this.setBIM)
      cb(false)
      return getUGM({ data: this.data, bim: this.bim })
    }

    const oldLineToNewLine = {}
    const newPoints = []
    const newLines = []
    const newRooms = []
    const newUnNamedRooms = []
    const newSmallRooms = []
    const newMainWalls = []
    const newDryWalls = []
    const newDoors = []
    const newWindows = []
    const newScanstations = []
    const newSeparators = []
    const newTexts = []
    const newMaterials = []

    const roomsNumber = bim.cols.room.length
    const MainWallsNumber = bim.cols.mainwall.length
    const DryWallsNumber = bim.cols.drywall.length
    const doorsNumber = bim.cols.door.filter(i => i.room).length
    const windowsNumber = bim.cols.window.filter(i => i.window).length

    const bimId = bim.cols.bim[0].id

    roomData.forEach((lineIds, index) => {
      const roomId = uuidv4()
      const points = []
      const lines = []
      for (let i = 0; i < lineIds.length; i++) {
        if (this.getTypeOfVariable(lineIds[i][0]) === 'Array') {
          const newPId = uuidv4()
          const newPoint = {
            ...data.cols.point[0],
            id: newPId,
            location: [lineIds[i][0][0], lineIds[i][0][1], 0],
            name: newPId,
            value: newPId,
            _id: null,
            isNew: true,
            updatedAt: null
          }
          newDataDocs[newPId] = newPoint
          newPoints.push(newPoint)
          points.push(lineIds[i][0])
          lineIds[i][0] = newPId
        } else {
          const pointId = lineIds[i][0]
          const point = newDataDocs[pointId]
          if (!point) console.log('点不存在!', pointId)
          const location = point.location
          points.push([location[0], location[1]])
        }
      }

      for (let i = 0; i < lineIds.length; i++) {
        lineIds[i][1].forEach(id => {
          if (this.getTypeOfVariable(id) === 'String') {
            let startPId
            let endPId
            if (i === lineIds.length - 1) {
              startPId = lineIds[i][0]
              endPId = lineIds[0][0]
            } else {
              startPId = lineIds[i][0]
              endPId = lineIds[i + 1][0]
            }
            if (newDataDocs[id]) {
              const definition = newDataDocs[id].definition
              if (
                definition === 'Line' ||
                definition === 'line' ||
                definition === 'Arc' ||
                definition === 'arc' ||
                definition === 'Ellipse' ||
                definition === 'ellipse'
              ) {
                const line = this.cutOut(id, startPId, endPId, newDataDocs, newLines, oldLineToNewLine)
                lines.push(line)
              } else {
                console.log('未支持的类型（不是线或者圆）', definition)
              }
            }
          } else {
            lines.push(id)
          }
        })
      }

      const [roomName, textId] = this.findTextInRoom(points)
      const ignoreFlag = this.caculateArea(points) < 2000000 ? true : false
      const newId = uuidv4()
      if (textId !== undefined) {
        const textData = this.data.docs[textId]
        newTexts.push({
          ...textData,
          origin: textData.id,
          id: newId,
          name: newId,
          value: newId,
          definition: 'displaytext',
          content: roomName || `${translate('room')}${newUnNamedRooms.length + 1}`
        })
      } else {
        if (!ignoreFlag) {
          const [roomName2, textId2] = this.findTextInRoom2(points)
          if (textId2 === undefined) {
            const layer = this.data.cols.layer.filter(i => i.name === 'Room')[0]
            let materialId = undefined
            let height = undefined
            if (this.data.cols.text[0] !== undefined) {
              materialId = this.data.cols.text[0].material
              height = this.data.cols.text[0].height
            } else {
              materialId = uuidv4()
              const oldMaterialData = this.data.cols.rendermaterial[0]
              newMaterials.push({ ...oldMaterialData, color: 255, id: materialId, name: materialId, value: materialId })
              height = 250
            }
            const center = this.getPolygonAreaCenter(points)
            const newPointId = uuidv4()
            const newPoint = {
              definition: 'point',
              id: newPointId,
              location: [center[0] - 120, center[1] - 87, 0],
              name: newPointId,
              value: newPointId,
              _id: null,
              isNew: true,
              updatedAt: null
            }
            newPoints.push(newPoint)
            newTexts.push({
              font: 'FangSong',
              height: height,
              insert: newPointId,
              origin: null,
              layer: layer.id,
              material: materialId,
              width: 250,
              rotation: 0,
              id: newId,
              name: newId,
              value: newId,
              definition: 'displaytext',
              content: roomName || `${translate('room')}${newUnNamedRooms.length + 1}`
            })
          } else {
            const textData = this.data.docs[textId2]
            newTexts.push({
              ...textData,
              origin: textData.id,
              id: newId,
              name: newId,
              value: newId,
              definition: 'displaytext',
              content: roomName || `${translate('room')}${newUnNamedRooms.length + 1}`
            })
          }
        }
      }

      const [direction, depthArr, bayArr] = orientationAndDimension[index]
      const depth = depthArr.map(data => {
        const [value, point1, point2] = data
        return {
          points: [point1, point2],
          value: Math.round(value / 10) * 10,
          id: uuidv4()
        }
      })
      const bay = bayArr.map(data => {
        const [value, point1, point2] = data
        return {
          points: [point1, point2],
          value: Math.round(value / 10) * 10,
          id: uuidv4()
        }
      })

      const room = {
        useText: ignoreFlag ? '' : newId,
        points,
        name: roomName || `${translate('room')}${newUnNamedRooms.length + 1}`,
        apartment: undefined,
        bim: bimId,
        id: roomId,
        ignore: ignoreFlag,
        mergeNum: index,
        definition: 'room',
        designValue: {
          bay: bay,
          depth: depth,
          clearHeight: 0
        }
      }
      if (roomName === undefined) {
        newUnNamedRooms.push(room)
      }
      newRooms.push(room)

      lines.forEach((line, lineIndex) => {
        if (this.getTypeOfVariable(line) !== 'Number') {
          const layer = newDataDocs[line.layer]
          if (layer.type === 'MainWall') {
            const newWall = {
              data: [line.id],
              lines: [[line.start, line.end]],
              name: `${translate('MainWall')}0${MainWallsNumber + newMainWalls.length + 1}`,
              room: roomId,
              original: line.original,
              id: uuidv4(),
              definition: 'mainwall'
            }
            newMainWalls.push(newWall)
          } else if (layer.type === 'DryWall') {
            const newWall = {
              data: [line.id],
              lines: [[line.start, line.end]],
              name: `${translate('DryWall')}0${DryWallsNumber + newDryWalls.length + 1}`,
              room: roomId,
              original: line.original,
              id: uuidv4(),
              definition: 'drywall'
            }
            newDryWalls.push(newWall)
          }
        } else if (line === 0) {
          const lastLine = lineIndex === 0 ? lines[lines.length - 1] : lines[lineIndex - 1]
          const nextLine = lineIndex === lines.length - 1 ? lines[0] : lines[lineIndex + 1]
          if (lastLine.start && nextLine.start) {
            const newDoor = {
              data: [],
              lines: [this.getDoorEndpoint(lastLine, nextLine, newDataDocs)],
              name: `${translate('door')}0${doorsNumber + newDoors.length + 1}`,
              room: roomId,
              material: lastLine.material,
              id: uuidv4(),
              definition: 'door'
            }
            newDoors.push(newDoor)
          }
        } else if (line === -1) {
          const lastLine = lineIndex === 0 ? lines[lines.length - 1] : lines[lineIndex - 1]
          const nextLine = lineIndex === lines.length - 1 ? lines[0] : lines[lineIndex + 1]
          if (lastLine.start && nextLine.start) {
            const newWindow = {
              data: [],
              lines: [this.getDoorEndpoint(lastLine, nextLine, newDataDocs)],
              name: `${translate('window')}0${windowsNumber + newWindows.length + 1}`,
              room: roomId,
              material: lastLine.material,
              id: uuidv4(),
              definition: 'window'
            }
            newWindows.push(newWindow)
          }
        }
      })
      const otherlines = scanstation[index].map(i => i[1])
      const _otherlines = cloneDeep(otherlines)
      const delArr = []
      otherlines.forEach((o, index1) => {
        _otherlines.forEach((p, index2) => {
          if (o.every(m => p.includes(m)) && index1 !== index2) {
            delArr.push(index1)
          }
        })
      })
      scanstation[index] = scanstation[index].filter(p => !delArr.includes(p))
      scanstation[index].forEach((i, index2) => {
        let [point, lines] = i
        lines = lines.map(id => {
          if (oldLineToNewLine[id]) {
            return oldLineToNewLine[id]
          } else {
            return id
          }
        })
        const drywalls = [...newDryWalls]
          .filter(o => o.room === roomId)
          .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
          .map(i => i.data[0])
        const mainwalls = [...newMainWalls]
          .filter(o => o.room === roomId)
          .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
          .map(i => i.data[0])
        const doors = [...newDoors]
          .filter(o => o.room === roomId)
          // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
          .map(i => i.id)
        const windows = [...newWindows]
          .filter(o => o.room === roomId)
          // .filter(a => lines.includes(a.original) || lines.includes(a.data[0]))
          .map(i => i.id)
        const scanstation = {
          point,
          id: roomId + `0${index2 + 1}`,
          drywalls,
          mainwalls,
          doors,
          windows,
          name: `${room.name}${translate('scanstation')}0${index2 + 1}`,
          room: roomId,
          definition: 'scanstation',
          stage: ['masonry', 'plaster']
        }
        if (
          !(
            roomName &&
            (roomName.search('卫') !== -1 ||
              roomName.search('厨房') !== -1 ||
              roomName.search('阳台') !== -1 ||
              roomName.search('梯') !== -1 ||
              roomName.search('设备') !== -1 ||
              roomName.search('井') !== -1)
          )
        ) {
          newScanstations.push(scanstation)
        }
        // newScanstations.push(scanstation)
      })
      separators[index].forEach((i, index2) => {
        const s_id = roomId + `sep0${index2 + 1}`
        const separator = {
          id: s_id,
          line: i,
          room: roomId,
          door: null,
          definition: 'separator',
          name: s_id,
          asDoor: false,
          isUsed: false,
          bim: bimId
        }
        newSeparators.push(separator)
      })
    })
    const roomIds = bim.cols.room.map(i => i.id)
    const drywallIds = bim.cols.drywall.map(i => i.id)
    const mainwallIds = bim.cols.mainwall.map(i => i.id)
    const doorIds = bim.cols.door.map(i => i.id)
    const windowIds = bim.cols.window.map(i => i.id)

    const displayTextIds = data.cols.displaytext.map(i => i.id)

    rxdb.deleteDocs(roomIds, 'room', this.data, this.bim, this.setData, this.setBIM)
    rxdb.deleteDocs(drywallIds, 'drywall', this.data, this.bim, this.setData, this.setBIM)
    rxdb.deleteDocs(mainwallIds, 'mainwall', this.data, this.bim, this.setData, this.setBIM)
    rxdb.deleteDocs(doorIds, 'door', this.data, this.bim, this.setData, this.setBIM)
    rxdb.deleteDocs(windowIds, 'window', this.data, this.bim, this.setData, this.setBIM)
    const separatorIds = bim.cols.separator.map(i => i.id)
    if (deleteSeparator) {
      rxdb.deleteDocs(separatorIds, 'separator', this.data, this.bim, this.setData, this.setBIM)
    }

    rxdb.deleteDocs(displayTextIds, 'displaytext', this.data, this.bim, this.setData, this.setBIM)

    if (!stage.includes('concrete')) {
      const apartmentIds = bim.cols.apartment.map(i => i.id)
      rxdb.deleteDocs(apartmentIds, 'apartment', this.data, this.bim, this.setData, this.setBIM)
      const scanstationIds = bim.cols.scanstation.filter(o => o.room).map(i => i.id)
      rxdb.deleteDocs(scanstationIds, 'scanstation', this.data, this.bim, this.setData, this.setBIM)
      // const lineIds = bim.cols.separator.map(i => i.door)
      // rxdb.deleteDocs(lineIds, 'line', this.data, this.bim, this.setData, this.setBIM)
      // rxdb.deleteDocs(separatorIds, 'separator', this.data, this.bim, this.setData, this.setBIM)
    }

    rxdb.addDocs(newPoints, 'point', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newLines, 'line', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newRooms, 'room', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newDryWalls, 'drywall', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newMainWalls, 'mainwall', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newDoors, 'door', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newWindows, 'window', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newScanstations, 'scanstation', this.data, this.bim, this.setData, this.setBIM)
    if (separatorIds.length === 0 || deleteSeparator)
      rxdb.addDocs(newSeparators, 'separator', this.data, this.bim, this.setData, this.setBIM)
    // rxdb.addDocs(newSeparators, 'separator', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newTexts, 'displaytext', this.data, this.bim, this.setData, this.setBIM)
    rxdb.addDocs(newMaterials, 'rendermaterial', this.data, this.bim, this.setData, this.setBIM)
    return getUGM({ data: this.data, bim: this.bim })
  }

  cutOut = (lineId, startPId, endPId, newDataDocs, newLines, oldLineToNewLine) => {
    let { start: lineStartPId, end: lineEndPId } = newDataDocs[lineId]
    let sign = false
    if (!lineStartPId || !lineEndPId) sign = true
    if (!lineStartPId) lineStartPId = newDataDocs[lineId].start_point
    if (!lineEndPId) lineEndPId = newDataDocs[lineId].end_point
    if (
      this.collinear3Points(lineStartPId, startPId, endPId, newDataDocs) &&
      this.collinear3Points(lineEndPId, startPId, endPId, newDataDocs)
    ) {
      const getDis2 = (startPId, endPId) => this.getDis([startPId, endPId], newDataDocs)
      const L = getDis2(startPId, endPId)
      const l1 = getDis2(lineStartPId, startPId)
      const l2 = getDis2(lineStartPId, endPId)
      const l3 = getDis2(lineEndPId, startPId)
      const l4 = getDis2(lineEndPId, endPId)
      if (l1 > L || l2 > L) {
        sign = true
        if (l1 > l2) {
          lineStartPId = endPId
        } else if (l1 < l2) {
          lineStartPId = startPId
        }
      }
      if (l3 > L || l4 > L) {
        sign = true
        if (l3 > l4) {
          lineEndPId = endPId
        } else if (l3 < l4) {
          lineEndPId = startPId
        }
      }
    }
    const lineLayerId = newDataDocs[lineId].layer
    // const lineLayerId = this.data.cols.layer.find(i => i.type === 'DryWall' || i.type === 'drywall').id
    // const lineLayerId = this.data.cols.layer.find(i => i.type === 'DryWall' || i.type === 'drywall').id
    if (sign) {
      const newlineId = uuidv4()
      oldLineToNewLine[lineId] = newlineId
      const newLine = {
        ...this.data.cols.line[0],
        end: lineEndPId,
        id: newlineId,
        layer: lineLayerId,
        name: newlineId,
        start: lineStartPId,
        updatedAt: null,
        value: newlineId,
        original: lineId,
        isNew: true,
        _id: null
      }
      newDataDocs[newlineId] = newLine
      newLines.push(newLine)
      return newLine
    } else {
      return newDataDocs[lineId]
    }
  }

  setData = data => (this.data = data)

  setBIM = bim => (this.bim = bim)

  setElements = elements => (this.elements = elements)

  getDoorEndpoint = (lastLine, nextLine, newDataDocs) => {
    const lastStartPId = lastLine.start
    const lastEndPId = lastLine.end
    const nextStartPId = nextLine.start
    const nextEndPId = nextLine.end
    const resArr = [
      [lastStartPId, nextStartPId],
      [lastStartPId, nextEndPId],
      [lastEndPId, nextStartPId],
      [lastEndPId, nextEndPId]
    ]
    const disArr = resArr.map(res => this.getDis(res, newDataDocs))
    const minIndex = disArr.findIndex(i => i === Math.min(...disArr))
    return resArr[minIndex]
  }

  //计算两点间的距离
  getDis = ([p1, p2], newDataDocs) => {
    p1 = this.getLocationCoord(p1, newDataDocs)
    p2 = this.getLocationCoord(p2, newDataDocs)
    const dx = Math.abs(p2[0] - p1[0])
    const dy = Math.abs(p2[1] - p1[1])
    return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2))
  }

  getLocationCoord = (id, newDataDocs) => {
    if (newDataDocs) {
      const location = newDataDocs[id].location
      const narrowCoord = coord => Math.round(coord)
      return [narrowCoord(location[0]), narrowCoord(location[1])]
    } else {
      const location = this.data.docs[id].location
      const narrowCoord = coord => Math.round(coord)
      return [narrowCoord(location[0]), narrowCoord(location[1])]
    }
  }

  getDoorEndpoint = (lastLine, nextLine, newDataDocs) => {
    const lastStartPId = lastLine.start
    const lastEndPId = lastLine.end
    const nextStartPId = nextLine.start
    const nextEndPId = nextLine.end
    const resArr = [
      [lastStartPId, nextStartPId],
      [lastStartPId, nextEndPId],
      [lastEndPId, nextStartPId],
      [lastEndPId, nextEndPId]
    ]
    const disArr = resArr.map(res => this.getDis(res, newDataDocs))
    const minIndex = disArr.findIndex(i => i === Math.min(...disArr))
    return resArr[minIndex]
  }

  findTextInRoom = points => {
    // const { data } = this
    // const texts = data.cols.text.map(i => [data.docs[i.insert].location[0], data.docs[i.insert].location[1]])
    // const possibleTexts = texts.filter(i => { if(this.isInPolygon(i, points)){return }})
    // console.log(possibleTexts)
    // const index = texts.findIndex(i => this.isInPolygon(i, points))
    // if (index > -1) return data.cols.text[index].content
    // console.log(this.roomNames)
    const { data } = this

    const texts = data.cols.text.map(i => {
      return { ...i, insert: [data.docs[i.insert].location[0], data.docs[i.insert].location[1]] }
    })
    const possibleTexts = texts.filter(i => this.isInPolygon(i.insert, points))
    // console.log(possibleTexts)
    if (possibleTexts.length > 1) {
      let minIndex = undefined
      let minIndex2 = undefined
      let textId = undefined
      possibleTexts.forEach(i => {
        const index = this.roomNames.necessary.findIndex(j => i.content === j)
        if (index !== -1) {
          if (minIndex === undefined) {
            minIndex = index
            textId = i.id
          } else {
            if (minIndex > index) {
              minIndex = index
              textId = i.id
            }
          }
        }
        // minIndex = minIndex === undefined && index !== -1 ? index : minIndex > index && index !== -1 ? index : minIndex
      })
      if (minIndex !== undefined) {
        return [this.roomNames.necessary[minIndex], textId]
      } else {
        possibleTexts.forEach(i => {
          const index2 = this.roomNames.secondary.findIndex(j => i.content.includes(j))
          if (minIndex2 === undefined && index2 !== -1) {
            minIndex2 = index2
            textId = i.id
          } else {
            if (minIndex2 > index2 && index2 !== -1) {
              minIndex2 = index2
              textId = i.id
            }
          }
        })

        if (minIndex2 !== undefined) {
          const newName = data.docs[textId].content
          return [newName, textId]
        }
        return []
      }
    } else {
      return possibleTexts[0] ? [possibleTexts[0].content, possibleTexts[0].id] : []
    }
  }

  // 查找displaytext是否已创建过文字
  findTextInRoom2 = points => {
    const { data } = this
    if (data.cols.displaytext) {
      const texts = data.cols.displaytext.map(i => {
        return { ...i, insert: [data.docs[i.insert].location[0], data.docs[i.insert].location[1]] }
      })
      const possibleTexts = texts.filter(i => this.isInPolygon(i.insert, points))
      // console.log(possibleTexts)
      if (possibleTexts.length > 1) {
        let minIndex = undefined
        let textId = undefined
        possibleTexts.forEach(i => {
          const index = this.roomNames.necessary.findIndex(j => i.content === j)
          if (minIndex === undefined && index !== -1) {
            minIndex = index
            textId = i.id
          } else {
            if (minIndex > index && index !== -1) {
              minIndex = index
              textId = i.id
            }
          }
          // minIndex = minIndex === undefined && index !== -1 ? index : minIndex > index && index !== -1 ? index : minIndex
        })
        if (minIndex !== undefined) {
          return [this.roomNames.necessary[minIndex], textId]
        } else {
          return []
        }
      } else {
        return possibleTexts[0] ? [possibleTexts[0].content, possibleTexts[0].id] : []
      }
    }
  }

  getPolygonAreaCenter = points => {
    if (points.length <= 2) {
      return []
    }

    let area = 0
    let x = 0
    let y = 0
    for (let i = 0; i < points.length; i++) {
      const lng = points[i][0]
      const lat = points[i][1]
      const nextlng = i === 0 ? points[points.length - 1][0] : points[i - 1][0]
      const nextlat = i === 0 ? points[points.length - 1][1] : points[i - 1][1]
      const tmp_area = (nextlng * lat - nextlat * lng) / 2
      area = area + tmp_area
      x = x + (tmp_area * (lng + nextlng)) / 3
      y = y + (tmp_area * (lat + nextlat)) / 3
    }
    x = x / area
    y = y / area
    return [Math.round(x), Math.round(y)]
  }

  getTypeOfVariable = variable => {
    const str = Object.prototype.toString.call(variable)
    return str.substring(8, str.length - 1)
  }

  isInPolygon = (checkPoint, polygonPoints) => {
    let counter = 0
    let i
    let xinters
    let p1, p2
    const pointCount = polygonPoints.length
    p1 = polygonPoints[0]

    for (i = 1; i <= pointCount; i++) {
      p2 = polygonPoints[i % pointCount]
      if (checkPoint[0] > Math.min(p1[0], p2[0]) && checkPoint[0] <= Math.max(p1[0], p2[0])) {
        if (checkPoint[1] <= Math.max(p1[1], p2[1])) {
          if (p1[0] !== p2[0]) {
            xinters = ((checkPoint[0] - p1[0]) * (p2[1] - p1[1])) / (p2[0] - p1[0]) + p1[1]
            if (p1[1] === p2[1] || checkPoint[1] <= xinters) {
              counter++
            }
          }
        }
      }
      p1 = p2
    }
    if (counter % 2 === 0) {
      return false
    } else {
      return true
    }
  }

  collinear3Points = (a, b, c, newDataDocs) => {
    //是否共线 海伦公式 S=sqrt(p(p-a)(p-b)(p-c)) p=(a+b+c)/2
    // eslint-disable-next-line no-undef
    const mathFloor = coord => Math.round(coord / 10)
    function distance(a, b) {
      const x1 = mathFloor(a[0]) - mathFloor(b[0])
      const y1 = mathFloor(a[1]) - mathFloor(b[1])
      const z1 = mathFloor(a[2]) - mathFloor(b[2])
      return Math.sqrt(x1 * x1 + y1 * y1 + z1 * z1)
    }
    const edge_A = distance(newDataDocs[a].location, newDataDocs[b].location)
    const edge_B = distance(newDataDocs[b].location, newDataDocs[c].location)
    const edge_C = distance(newDataDocs[a].location, newDataDocs[c].location)

    const p = 0.5 * (edge_A + edge_B + edge_C)
    if (p * (p - edge_A) * (p - edge_B) * (p - edge_C)) return false //面积大于零 就是一个三角形 三点不共线
    return true
  }

  divideRegions = (regions, roomInfos) => {
    const dataDocs = cloneDeep(this.data.docs)
    // const bimDocs = cloneDeep(this.bim.docs)
    const oldRooms = cloneDeep(this.bim.cols.room)
    const oldRoomDocs = cloneDeep(this.bim.docs)
    const oldSeparatorDocs = cloneDeep(this.bim.docs)
    const newRoomData = []

    for (const key in regions) {
      const newRegions = []
      const areas = regions[key]
      console.log(areas)
      const roomData = oldRooms.filter(i => i.mergeNum === parseInt(key))
      for (const region of areas) {
        const points = []
        for (const line of region) {
          const point = line[0]
          console.log(point)
          if (typeof point === 'string') {
            const location = dataDocs[point].location
            points.push([location[0], location[1]])
          } else {
            points.push(point)
          }
        }
        console.log(points)
        newRegions.push({ points: [...points] })
      }
      newRoomData.push({ ...roomData[0], regions: [...newRegions] })
    }
    for (const key in roomInfos) {
      const roomData = cloneDeep(oldRoomDocs[key])
      const sepState = roomInfos[key]
      const remain = sepState.use.length + sepState.origin.length - sepState.delete.length
      if (remain === 0) {
        console.log(roomData)
        delete roomData['regions']
        console.log(roomData)
        newRoomData.push({ ...roomData })
      }
    }
    console.log(newRoomData)
    if (newRoomData.length > 0) {
      rxdb.updateDocs(newRoomData, 'room', this.data, this.bim, this.setData, this.setBIM)
    }
    const newSeparators = []
    for (const key in roomInfos) {
      const sepState = roomInfos[key]
      for (const sep of sepState.use) {
        const oldSeparator = oldSeparatorDocs[sep.id]
        const newSeparator = { ...oldSeparator, isUsed: true }
        newSeparators.push(newSeparator)
      }
      for (const sep of sepState.delete) {
        const oldSeparator = oldSeparatorDocs[sep.id]
        const newSeparator = { ...oldSeparator, isUsed: false }
        newSeparators.push(newSeparator)
      }
    }
    rxdb.updateDocs(newSeparators, 'separator', this.data, this.bim, this.setData, this.setBIM)

    return getUGM({ data: this.data, bim: this.bim })
  }

  caculateArea = points => {
    let arrlength = points.length
    let area = 0
    for (let i = 0; i < arrlength; i++) {
      let pointA = points[i]
      let pointB = undefined
      if (i === arrlength - 1) {
        pointB = points[0]
      } else {
        pointB = points[i + 1]
      }
      area += pointA[0] * pointB[1] - pointA[1] * pointB[0]
    }

    return Math.abs(area) / 2
  }

  getData = () => this.data
  getBIM = () => this.bim
  getElements = () => this.elements
}

module.exports = Autoplan
